package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domin.po.PointsRecord;
import com.tianji.learning.domin.vo.PointsStatisticsVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.query.PointsRecordPageQuery;
import com.tianji.learning.service.IPointsRecordService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 学习积分记录，每个月底清零 服务实现类
 * </p>
 *
 * @author author
 * @since 2023-11-09
 */
@Service
@RequiredArgsConstructor
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord> implements IPointsRecordService {

    private final StringRedisTemplate redisTemplate;

    @Override
    public void addPointsRecords(Long userId, Integer points, PointsRecordType type) {

        int realPoints = points;

        //查询当前用户该分类当日的积分是否达到上限
        int maxPoints = type.getMaxPoints();

        if (maxPoints > 0) {
            int cuntPoints = queryUserPointsByTypeAndDate(userId, type);


            if (cuntPoints >= maxPoints) {
                return;
            }
            if (cuntPoints + points > maxPoints) {
                realPoints = maxPoints;
            }
        }

        //保存积分
        PointsRecord record = new PointsRecord();

        record.setUserId(userId);
        record.setType(type.getValue());
        record.setPoints(realPoints);
        save(record);
        //更新积分到redis
        LocalDate now = LocalDate.now();
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + now.format(DateUtils.POINTS_BOARD_SUFFIX_FORMATTER);
        redisTemplate.opsForZSet().incrementScore(key, userId.toString(), realPoints);
    }

    @Override
    public List<PointsStatisticsVO> queryMyPointsToday() {

        //获取当前用户id
        Long userId = UserContext.getUser();
        //查询积分表 条件：今天日期、当前用户id


        QueryWrapper<PointsRecord> wrapper = new QueryWrapper<>();

        wrapper.lambda().eq(PointsRecord::getUserId, 2).apply("DATE(create_time) = {0}", LocalDate.now()).groupBy(PointsRecord::getType);

        List<PointsRecord> list = getBaseMapper().queryUserPointsByDate(wrapper);
        //封装VO返回
        ArrayList<PointsStatisticsVO> vos = new ArrayList<>();
        for (PointsRecord pointsRecord : list) {
            PointsStatisticsVO pointsStatisticsVO = new PointsStatisticsVO();

            PointsRecordType pointsRecordType = PointsRecordType.of(pointsRecord.getType());
            pointsStatisticsVO.setType(pointsRecordType.getDesc());
            pointsStatisticsVO.setMaxPoints(pointsRecordType.getMaxPoints() == 0 ? 999 : pointsRecordType.getMaxPoints());
            pointsStatisticsVO.setPoints(pointsRecord.getPoints());
            vos.add(pointsStatisticsVO);
        }
        return vos;
    }

    @Override
    public void createTable(String tableName) {
        getBaseMapper().createTable(tableName);
    }

    @Override
    public List<PointsRecord> queryPointsRecordList(PointsRecordPageQuery query) {
        //根据年月查询
        Page<PointsRecord> page = lambdaQuery().apply("YEAR(create_time) = {0} AND MONTH(create_time) = {1}", query.getDate().getYear(),query.getDate().getMonth()).page(query.toMpPage());
        return page.getRecords();
    }

    private int queryUserPointsByTypeAndDate(Long userId, PointsRecordType type) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime dayStartTime = DateUtils.getDayStartTime(now);
        LocalDateTime dayEndTime = DateUtils.getDayEndTime(now);

        QueryWrapper<PointsRecord> wrapper = new QueryWrapper<>();

        wrapper.lambda().eq(PointsRecord::getUserId, userId).eq(PointsRecord::getType, type.getValue()).between(PointsRecord::getCreateTime, dayStartTime, dayEndTime);

        Integer points = getBaseMapper().queryUserPointsByTypeAndDate(wrapper);
        return points == null ? 0 : points;
    }
}
